package com.rules.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gillion.grule.client.core.DataType;

import com.gillion.grule.client.utils.Closure;
import com.gillion.grule.client.utils.Streams;

import com.rules.admin.dao.UnitCaseDao;
import com.rules.admin.entity.UnitCase;
import com.rules.admin.entity.UnitCaseExpectAction;
import com.rules.admin.entity.UnitCaseExpectAsset;
import com.rules.admin.entity.UnitCaseExpectResult;
import com.rules.admin.entity.UnitCaseMock;
import com.rules.admin.entity.UnitCaseParam;
import com.rules.admin.exceptions.BusinessRuntimeException;
import com.rules.admin.service.UnitCaseMockService;
import com.rules.admin.service.UnitCaseParamService;

import com.rules.admin.unit.UnitCaseBuilder;
import com.rules.admin.unit.expect.AssetExpect;
import com.rules.admin.unit.expect.ActionExpect;
import com.rules.admin.unit.expect.ResultExpect;
import com.rules.admin.unit.mock.ComponentMock;
import com.rules.admin.utils.JSONUtils;
import com.rules.admin.service.UnitCaseExpectActionService;
import com.rules.admin.service.UnitCaseExpectAssetService;
import com.rules.admin.service.UnitCaseExpectResultService;
import com.rules.admin.service.UnitCaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

@Service
public class UnitCaseServiceImpl extends ServiceImpl<UnitCaseDao, UnitCase> implements UnitCaseService {
   @Autowired
   private UnitCaseExpectActionService unitCaseExpectActionService;
   @Autowired
   private UnitCaseExpectAssetService unitCaseExpectAssetService;
   @Autowired
   private UnitCaseExpectResultService unitCaseExpectResultService;
   @Autowired
   private UnitCaseParamService unitCaseParamService;
   @Autowired
   private UnitCaseMockService unitCaseMockService;

   public com.rules.admin.unit.UnitCase converterToUnitCase(Long id) {
      UnitCase unitCase = (UnitCase)this.getById(id);
      final UnitCaseBuilder unitCaseBuilder = UnitCaseBuilder.newBuilder().groupId(unitCase.getGroupId()).artifactId(unitCase.getArtifactId()).unitCaseName(unitCase.getUnitCaseName());
      Streams.of(this.unitCaseExpectActionService.getAllActionByCaseId(id)).forEach(new Closure<UnitCaseExpectAction>() {
         public void execute(UnitCaseExpectAction expectAction) {
            ActionExpect actionExpect = new ActionExpect();
            actionExpect.setExpectRuleName(expectAction.getActionName());
            unitCaseBuilder.addExpect(actionExpect);
         }
      });
      Streams.of(this.unitCaseExpectAssetService.getAllAssetByCaseId(id)).forEach(new Closure<UnitCaseExpectAsset>() {
         public void execute(UnitCaseExpectAsset expectAsset) {
            AssetExpect assetExpect = new AssetExpect();
            assetExpect.setAssertExpression(expectAsset.getExpression());
            unitCaseBuilder.addExpect(assetExpect);
         }
      });
      List<UnitCaseExpectResult> expectResult = this.unitCaseExpectResultService.findExpectResultByCaseId(id);
      if (!expectResult.isEmpty()) {
         ResultExpect resultExpect = new ResultExpect();
         resultExpect.setExpectResult(JSONUtils.read(((UnitCaseExpectResult)expectResult.get(0)).getExpectResult()));
         unitCaseBuilder.addExpect(resultExpect);
      }

      final List<UnitCaseParam> paramList = this.unitCaseParamService.getParamByCaseId(id);
      Streams.of(paramList).forEach(new Closure<UnitCaseParam>() {
         public void execute(UnitCaseParam unitCaseParam) {
            if (unitCaseParam.getParentId() == null) {
               if (unitCaseParam.getDataType() == DataType.Object) {
                  Map map = new HashMap();
                  Iterator var3 = paramList.iterator();

                  while(var3.hasNext()) {
                     UnitCaseParam param = (UnitCaseParam)var3.next();
                     if (param.getParentId() != null && param.getParentId().equals(unitCaseParam.getId())) {
                        if (param.getDataType() == DataType.Object) {
                           map.put(param.getParamName(), UnitCaseServiceImpl.this.convertParam(param, paramList));
                        } else {
                           map.put(param.getParamName(), UnitCaseServiceImpl.this.convertParam(param));
                        }
                     }
                  }

                  unitCaseBuilder.addParams(JSON.toJSON(map));
               } else {
                  unitCaseBuilder.addParams(UnitCaseServiceImpl.this.convertParam(unitCaseParam));
               }
            }

         }
      });
      List<UnitCaseMock> mockList = this.unitCaseMockService.getAllMocksByCaseId(id);
      Streams.of(mockList).forEach(new Closure<UnitCaseMock>() {
         public void execute(UnitCaseMock mock) {
            ComponentMock componentMock = new ComponentMock();
            componentMock.setMockValue(mock.getMockValue());
            componentMock.setMockComponent(mock.getMockComponent());
            componentMock.setMockExpression(mock.getMockExpression());
            unitCaseBuilder.addMock(componentMock);
         }
      });
      return unitCaseBuilder.build();
   }

   private Object convertParam(UnitCaseParam unitCaseParam) {
      Object result = null;
      if (unitCaseParam.getDataType() == DataType.Integer) {
         result = Integer.valueOf(unitCaseParam.getParam());
      } else if (unitCaseParam.getDataType() == DataType.String) {
         if ("null".equals(unitCaseParam.getParam())) {
            result = null;
         } else if ("''".equals(unitCaseParam.getParam())) {
            result = "";
         } else {
            result = unitCaseParam.getParam();
         }
      } else if (unitCaseParam.getDataType() == DataType.Double) {
         result = new BigDecimal(unitCaseParam.getParam());
      } else if (unitCaseParam.getDataType() == DataType.Boolean) {
         result = Boolean.valueOf(unitCaseParam.getParam());
      } else if (unitCaseParam.getDataType() == DataType.List) {
         result = JSON.parse(unitCaseParam.getParam());
      } else if (unitCaseParam.getDataType() == DataType.Long) {
         result = Long.parseLong(unitCaseParam.getParam());
      } else if (unitCaseParam.getDataType() == DataType.Date) {
         result = new Date(Long.parseLong(unitCaseParam.getParam()));
      }

      return result;
   }

   private Object convertParam(UnitCaseParam unitCaseParam, List<UnitCaseParam> paramList) {
      Object obj = null;
      Map map = new HashMap();
      Iterator var5 = paramList.iterator();

      while(var5.hasNext()) {
         UnitCaseParam param = (UnitCaseParam)var5.next();
         if (param.getParentId() != null && param.getParentId().equals(unitCaseParam.getId())) {
            if (param.getDataType() == DataType.Object) {
               map.put(param.getParamName(), this.convertParam(param, paramList));
            } else {
               map.put(param.getParamName(), this.convertParam(param));
            }
         }
      }

      return map;
   }

   public List<UnitCase> selectUnitCasesByPackage(String groupId, String artifactId) {
      LambdaQueryWrapper<UnitCase> queryWrapper = new LambdaQueryWrapper<>();
      queryWrapper.eq(UnitCase::getArtifactId,artifactId);
      queryWrapper.eq(UnitCase::getGroupId,groupId);
      return this.baseMapper.selectList(queryWrapper);
   }

   public UnitCase saveUnitCase(UnitCase unitCase) {
      LambdaQueryWrapper<UnitCase> queryWrapper = new LambdaQueryWrapper<>();
      if (unitCase.getId() != null) {
         queryWrapper.ne(UnitCase::getId,unitCase.getId());
      }
      queryWrapper.eq(UnitCase::getUnitCaseName,unitCase.getUnitCaseName());
      if (this.baseMapper.selectOne(queryWrapper) != null) {
         throw new BusinessRuntimeException("用例名称" + unitCase.getUnitCaseName() + "重复，必须唯一。");
      } else {
         this.save(unitCase);
         return unitCase;
      }
   }

   public void updateByGroupId(String oldGroupId, String newGroupId) {
      LambdaQueryWrapper<UnitCase> queryWrapper = new LambdaQueryWrapper<>();
      queryWrapper.eq(UnitCase::getGroupId,oldGroupId);

      List<UnitCase> unitCases = this.baseMapper.selectList(queryWrapper);

      for(int i = 0; i < unitCases.size(); ++i) {
         ((UnitCase)unitCases.get(i)).setGroupId(newGroupId);
      }
      this.saveOrUpdateBatch(unitCases);

   }

   public void updateByArtifactId(String oldArtifactId, String newArtifactId, String groupId) {
      LambdaQueryWrapper<UnitCase> queryWrapper = new LambdaQueryWrapper<>();
      queryWrapper.eq(UnitCase::getGroupId,groupId);
      queryWrapper.eq(UnitCase::getArtifactId,oldArtifactId);
      List<UnitCase> unitCases = this.baseMapper.selectList(queryWrapper);


      for(int i = 0; i < unitCases.size(); ++i) {
         ((UnitCase)unitCases.get(i)).setArtifactId(newArtifactId);
      }
      this.saveOrUpdateBatch(unitCases);

   }

   @Override
   public IPage<UnitCase> getUnitCaseByGroupIdandArtifactId(String groupId, String artifactId, IPage<UnitCase> page) {
      LambdaQueryWrapper<UnitCase> queryWrapper = new LambdaQueryWrapper<>();
      queryWrapper.eq(UnitCase::getGroupId,groupId);
      queryWrapper.eq(UnitCase::getArtifactId,artifactId);
      return this.page(page, queryWrapper);
   }

   public static void main(String[] args) {
      String a = "[\n    {\n        'customerCode': 'CP00041',\n        'transportType': '否',\n        'customerOrderId': 'CP00041',\n        'orderWithDetialJsonDTO':[\n            {\n                'orderType': 'YTR2'\n            },\n            {\n                'orderType': 'YTR3'\n            },\n            {\n                'orderType': 'YTR2'\n            }\n        ]\n    },\n    {\n        'customerCode': 'CP00041',\n        'transportType': '是',\n        'customerOrderId': 'CP00041',\n        'orderWithDetialJsonDTO':[\n            {\n                'orderType': 'YTR2'\n            },\n            {\n                'orderType': 'YTR3'\n            },\n            {\n                'orderType': 'YTR2'\n            }\n        ]\n    },\n    {\n        'customerCode': 'CP00041',\n        'transportType': '是',\n        'customerOrderId': 'CP00041',\n        'orderWithDetialJsonDTO':[\n            {\n                'orderType': 'YTR2'\n            },\n            {\n                'orderType': 'YTR3'\n            },\n            {\n                'orderType': 'YTR2'\n            }\n        ]\n    }\n]";
      JSON.parse(a);
   }
}
